import pygame
from settings import Settings
import random

# settings对象
st_obj = Settings()
# 获取活动范围长宽
width = st_obj.screen_width
height = st_obj.screen_height

# 获取格子的大小
size = st_obj.size


# 蛇的属性
snake_color = st_obj.snake_color
head_color = st_obj.head_color

# 墙的属性
wall_color = st_obj.wall_color

# 炸弹属性
bomb_color = st_obj.bomb_color
friend_color = st_obj.friend_color


# 常量
UP = 1          # w
LEFT = 2        # a
DOWN = 3        # s
RIGHT = 4       # d

# 基类


# 蛇节点类
class SnakeNode:
    def __init__(self, pos):
        self.pos = pos
        self.color = snake_color
        self.size = size

    def draw(self, screen):
        pygame.draw.rect(screen, self.color, (self.pos[0], self.pos[1], self.size, self.size), 0)
        # 节点外边框
        pygame.draw.rect(screen, (100, 100, 100), (self.pos[0], self.pos[1], self.size, self.size), 1)
    pass


# 蛇类
class Snake:
    def __init__(self):
        self.size = size
        # 内部变量加前缀 _
        self._nodes = []     # 蛇的节点
        self._dir = LEFT     # 蛇的方向，初始时向左
        self._is_eat = False     # 是否吃到炸弹
        self._aline = True      # 蛇是否存活
        self.friends = []       # 蛇发射的炸弹

        for i in range(3):
            # 初始化3个节点，放到nodes中
            node = SnakeNode((240 + i * 20, 240))
            self._nodes.append(node)

    # 绘制
    def draw(self, screen):
        # 先画头以外的节点
        for node in self._nodes[1:]:
            node.draw(screen)
        # 最后画头
        pygame.draw.rect(screen, head_color, (self._nodes[0].pos[0], self._nodes[0].pos[1], self.size, self.size), 0)
    # 移动
    def move(self):
        # 获取蛇头当前的位置，和参数
        head = self._nodes[0]
        x, y = head.pos[0], head.pos[1]
        if self._dir == LEFT:
            x = x - 20
        elif self._dir == RIGHT:
            x = x + 20
        elif self._dir == UP:
            y = y - 20
        else:
            y = y + 20

        new_head = SnakeNode((x, y))
        self._nodes.insert(0, new_head)

        # 判断是否吃到炸弹
        if self._is_eat:
            # 如果吃到， 长度加1 ，最后一个节点不动
            self._is_eat = False
        else:
            # 如果没吃到， 长度不变，最后一个节点去掉
            self._nodes.pop()

    # 改变方向
    def change_dir(self, new_dir):
        # 如果和当前方向不同，且不为反方向，则改变方向
        if self._dir != new_dir and (new_dir + self._dir) % 2 != 0:
            self._dir = new_dir

    # 出界， 参数改为box
    def out_wall(self, tick):
        head = self._nodes[0]
        # 判上, 如果蛇头超过活动范围上边
        if head.pos[1] < 20*tick:
            self._aline = False
        # 下边
        if head.pos[1] + 20 > height - 20*tick:
            self._aline = False
        # 左边
        if head.pos[0] < 20*tick:
            self._aline = False
        # 右边
        if head.pos[0] + 20 > width - 20*tick:
            self._aline = False

    # 吃到炸弹
    def eat_bomb(self, bomb):
        if self._nodes[0].pos[0]+10 == bomb.pos[0] and self._nodes[0].pos[1] + 10 == bomb.pos[1]:
            self._is_eat = True
            return True
        # 炸弹移动到半格的位置时上边的判定失效

        if bomb.pos[0] == self._nodes[0].pos[0] + 10 and abs(bomb.pos[1] - self._nodes[0].pos[1]) <= 10:
            self._is_eat = True
            return True
        # 横向
        if bomb.pos[1] == self._nodes[0].pos[1] + 10 and abs(bomb.pos[0] - self._nodes[0].pos[0]) <= 15:
            self._is_eat = True
            return True

        return False


    def shoot(self):
        if len(self._nodes) > 0:
            self._nodes.pop()
            friend = Bomb(friend_color, self, 0)

            dir_ = self._dir
            if dir_ == LEFT:
                friend.pos = (self._nodes[0].pos[0] - 60, self._nodes[0].pos[1]+10)
            if dir_ == RIGHT:
                friend.pos = (self._nodes[0].pos[0] + 60, self._nodes[0].pos[1]+10)
            if dir_ == UP:
                friend.pos = (self._nodes[0].pos[0]+10, self._nodes[0].pos[1] - 60)
            if dir_ == DOWN:
                friend.pos = (self._nodes[0].pos[0]+10, self._nodes[0].pos[1] + 60)
            friend._dir = self._dir
            friend.friend = True
            self.friends.append(friend)



    # 吃到自己
    def eat_self(self):
        head = self._nodes[0]
        for node in self._nodes[1:]:
            if node.pos == head.pos:
                self._aline = False

    # 撞到大本营



# 墙类，随着分数提高，范围变小
class Wall:
    def __init__(self, tick):
        self.tick = tick    # 墙的厚度
        pass

    # 绘制
    def draw(self, screen):
        pygame.draw.rect(screen, wall_color, (0, 0, width, height), self.tick*2)
        pass


    pass


# 炸弹类
class Bomb:
    # 添加参数 friend由外部传入, 去掉snake， tick 碰撞函数移到外部
    def __init__(self, color, snake, tick):
        x, y, can_move = self.create(snake, tick)
        self.pos = (x, y)
        self._dir = 0
        self.color = color
        self.friend = False     # 是敌对还是友好, 敌对黑色，友好蓝色
        self.can_move = can_move

        self.move()


    # 向基地移动
    def move(self):
        # 如果是敌对炸弹
        if self.friend == False:
            # 判断距离， 如果距大本营过远，可以移动,
            # 在创建时进行判断，可以移动将can_move置为True
            # 先横向移动到和大本营垂直的位置，再移动到大本营
            # 先判断能否移动
            if self.can_move:
                # 在左边
                if (width // 2) - self.pos[0] > 0:
                    self.pos = (self.pos[0] + 10, self.pos[1])
                # 在右边
                if self.pos[0] - (width // 2) > 0:
                    self.pos = (self.pos[0] - 10, self.pos[1])
                # 如果与大本营垂直
                if abs(self.pos[0] - (width // 2)) < 20:
                    # 在上边，向下移动
                    if self.pos[1] - (height // 2) < 0:
                        self.pos = (self.pos[0], self.pos[1] + 10)
                        # 在下边，向上
                    if self.pos[1] - (height // 2) > 0:
                        self.pos = (self.pos[0], self.pos[1] - 10)
        # 如果是自己发射的，按蛇的方向向前移动
        else:
            if self._dir == LEFT:
                self.pos = (self.pos[0] - 30, self.pos[1])
            if self._dir == RIGHT:
                self.pos = (self.pos[0] + 30, self.pos[1])
            if self._dir == UP:
                self.pos = (self.pos[0], self.pos[1] - 30)
            if self._dir == DOWN:
                self.pos = (self.pos[0], self.pos[1]+30)
            pass
        pass

    # # 炸到大本营
    # def boom_home(self):
    #     if self.friend == False:
    #         pass
    #     pass
    #
    # # 敌对炸弹相遇
    # def boom_each(self):
    #     pass

    # 随机生成一个炸弹的坐标
    def create(self, snake, tick):
        tick = tick+1   # 防止在边界生成，导致吃到炸弹后，卡在墙里
        x = random.randrange(tick * 20 + 10, width-10-tick*20, 20)
        y = random.randrange(tick * 20 + 10, height-10-tick*20, 20)
        can_move = False
        if abs(x - (width // 2)) > 10 * 20:
            can_move = True
        # 判断位置是否合适
        # 随机在大本营， 重新随机
        if x > (width // 2) - 20 and x < (width // 2) + 20 and y > (height // 2) - 20 and y < (height // 2) + 20:
            self.create(snake, tick)

        # 随机在蛇的节点， 重新随机
        for node in snake._nodes:
            if x == node.pos[0] and y == node.pos[1]:
                self.create(snake, tick)
        # 随机在墙里，修改随机范围
        return x, y, can_move

    def draw(self, screen):
        pygame.draw.circle(screen, self.color,self.pos, size // 2, 0)
        # pygame.draw.rect(screen, (0, 0, 0), (self.pos[0], self.pos[1], 20, 20), 1)

    # 炸弹碰撞
    def manage_bomb(self, bomb, tick):

        if self.friend:
            # 判断有没有出界
            if self.pos[0] - 10 < tick * 20 or self.pos[0] - 10 > width - tick * 20 or self.pos[1] - 10 < tick * 20 or \
                    self.pos[1] - 10 > height - tick * 20:
                # 如果返回1， 删除， 并从snake。friends中移除， 在外部删除，否则可能空对象，使用remove（friend) 或del friends[index]
                del self
                return 1
            # 如果是蛇发射的炸弹，判断有没有碰到敌对炸弹
            if self.pos == bomb.pos:
                del self
                del bomb
                # 如果返回2，从snake.friends中移除，同时生成新的炸弹
                return 2
            # 与移动中的炸弹碰撞
            elif self.pos[1] == bomb.pos[1] and abs(self.pos[0] - bomb.pos[0]) < 35:
                del self
                del bomb
                # 如果返回2，从snake.friends中移除，同时生成新的炸弹
                return 2
        # 敌对炸弹
        else:
            # 如果是敌对炸弹， 判断有没有碰到大本营
            # 将大本营分成四格， 每碰到一格，将该格大本营销毁
            if self.pos[0] > (width // 2) - 20 and self.pos[0] < (width // 2) + 20 and self.pos[1] > (height // 2) - 20 and self.pos[1] < (height // 2) + 20:
                del self
                # 返回3，将大本营血量-1， 删除该炸弹，并创建新炸弹对象
                return 3
        # 返回4,什么都不做， 或返回False，测试一下可不可以
        return 4


# 大本营类
class Home:
    def __init__(self):
        self.color = (233, 0, 0)
        self.size = 40
        self.pos = ((width // 2) - (self.size // 2), (height // 2) - (self.size // 2))

    def draw(self, screen):
        pygame.draw.rect(screen, self.color, (self.pos[0], self.pos[1], self.size, self.size), 0)

# 方法
# 在空闲位置随机生成炸弹
# 如果距离大于5，向大本营移动
def create_bomb(snake, wall, home):
    #
    pass





# 转向过快容易碰到自己，先判断头和第二节身体的

# 还是会从蛇的节点中生成炸弹

# 吃从右向左运动的炸弹会延迟判定
